package cz.cuni.amis.episodic.lisp.behan;

import cz.cuni.amis.episodic.lisp.behan.EventProcessor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.ListIterator;

/**
 *
 * @author behan
 */
public class TraceToEventVisitor extends TraceVisitor {
    ArrayList<EventProcessor> proc;

    // Constructor for ArrayList of processors
    public TraceToEventVisitor(ArrayList<ArrayList<String>> _trace, ArrayList<String> data, PrintWriter fout, ArrayList<EventProcessor> _proc) {
        super(_trace, data, fout);
        proc = new ArrayList<EventProcessor>(_proc);
    }

    // Constructor for just 1 processor
    public TraceToEventVisitor(ArrayList<ArrayList<String>> _trace, ArrayList<String> data, PrintWriter fout, EventProcessor _proc) {
        super(_trace, data, fout);
        proc = new ArrayList<EventProcessor>();
        proc.add(_proc);
    }

    public Visitor<ArrayList<String>> visitTree(VisitableTree<ArrayList<String>> tree) {
        return new TraceToEventVisitor(trace, tree.showdata(), out, proc);
    }

    public boolean visitData(VisitableTree<ArrayList<String>> parent, ArrayList<String> data, boolean isLeaf) throws java.io.IOException {
        // Name of current node, item 0
        String name = data.get(0);

        // List of affordances for current node, items 1..N
        ArrayList<String> affordances = new ArrayList<String>();
        affordances.addAll(data.subList(1, data.size()));
        //out.write(String.format("%s\nAffordances:", name));
        //int i;
        //for(i = 1; i < data.size(); i++) {
        //    out.write(String.format("%s", data.get(i)));
        //}
        //out.write("\n");

        ListIterator<EventProcessor> it = proc.listIterator();
        boolean ret = true;
        if (!isLeaf) {
            // Not a leaf = goal
            while (it.hasNext()) {
                ret &= it.next().openNode(name, nameTrace(), affordances);
            }
            return ret;
        } else {
            // leaf = Atomic action
            // TODO: hardcoded time is bad
            while (it.hasNext()) {
                ret &= it.next().atomicAction(name, nameTrace(), affordances);
            }
            return ret;
        }
    }

    public boolean postVisitData(VisitableTree<ArrayList<String>> parent, ArrayList<String> data, boolean isLeaf) throws java.io.IOException {
        // Name of current node, item 0
        String name = data.get(0);

        ListIterator<EventProcessor> it = proc.listIterator();
        boolean ret = true;
        if (!isLeaf) {
            while (it.hasNext()) {
                ret &= it.next().closeNode(name, nameTrace());
            }
        }
        // NOTE: No closing for atomic actions

        return true;
    }

    private ArrayList<String> nameTrace() {
        // A trace of goal names, no affordances
        ArrayList<String> nameTrace = new ArrayList<String>();

        ListIterator<ArrayList<String>> iter = trace.listIterator();
        if (iter.hasNext()) {
            ArrayList<String> elem = iter.next();

            while(iter.hasNext()) {
                nameTrace.add(elem.get(0));
                elem = iter.next();
            }
            // NOTE: The last element is the current one, do not add.
        }
        return nameTrace;
    }
}
